package de.koller.gravity.scene.fire;

import de.koller.aframe.util.filter.Combine;
import de.koller.aframe.util.filter.Convolution;
import de.koller.aframe.util.math.IFunction;
import de.koller.aframe.util.misc.BufferedRandomFloat;
import de.koller.aframe.util.misc.ColorGradient;
import de.koller.aframe.util.noise.n2D.Perlin2D;
import de.koller.aframe.util.noise.n2D.ScrollingPerlin2D;
import de.koller.aframe.util.resource.IOLoader;
import de.koller.gravity.scene.Scene;
import de.koller.oceanFramework.gl.util.RasterManager;
import de.koller.oceanFramework.util.MOut;
import java.awt.image.BufferedImage;
import java.util.Random;

//				HD = 27M
//ffmpeg -r 10 -b 1800 -i %03d.jpg test1800.mp4
//ffplay [file]
public class FireScene extends Scene {
	public Random rnd = new Random();
	public int width = 100;
	public int height = 100;
	
	private final BufferedRandomFloat bfr1 = new BufferedRandomFloat( "./temp/bfr/fire_scene_Perlin_1", rnd );
	private final BufferedRandomFloat bfrd = new BufferedRandomFloat( "./temp/bfr/fire_scene_Perlin_disortion", rnd );
	private final ScrollingPerlin2D perlin;
	private final ScrollingPerlin2D disortion;
	
	private final FireDispose fireDispose = new FireDispose();
	private final int framesPerPerlin = 24;
	
	public static void main( String[] args ) {
//		MOut o = new MOut( "./temp/mov/fire/tmp.tmp", true );
//		o.writeInt( 0 );
//		o.close();
//
//		ExecutorService s = Executors.newFixedThreadPool( 2 );	
//		final FireScene f = new FireScene();
//		
//		for( int i = 0; i < 10; i++ ) {
//			final int j = i;
//			s.execute( new Runnable() {
//				@Override public void run() {
//					IOLoader.savePNG( f.renderScene( j ), "./temp/mov/fire/" + j + ".png" );
//				}
//			});
//		}
//		
//		try {
//			s.shutdown();
//			s.awaitTermination( 1, TimeUnit.DAYS );
//		} catch ( InterruptedException ex ) {}
		
		MOut o = new MOut( "./temp/mov/fireGIF/tmp.tmp", true );
		o.writeInt( 0 );
		o.close();
		
		FireScene f = new FireScene();
		
		for( int i = 0; i < 24; i++ ) {
			final int j = i;
			IOLoader.savePNG( f.renderScene( j ), "./temp/mov/fireGIF/" + j + ".png" );
		}
	}

	public FireScene() {
		this.perlin = new ScrollingPerlin2D( bfr1, 6, .9f );
		this.perlin.normalizeMaxBound( Perlin2D.maxHeight( 0, 6, .9f ) );
		
		this.disortion = new ScrollingPerlin2D( bfrd, 3, .5f );
		this.disortion.normalizeMaxBound( Perlin2D.maxHeight( 0, 3, .5f ) );
	}
	
	@Override
	public BufferedImage renderScene() {
		return renderScene( 12 );
	}
	
	public BufferedImage renderScene( int frame ) {
		System.out.println( "render frame: " + frame );
		
		RasterManager r = new RasterManager( width, height );
		
		for( int x = 0; x < width; x++ )
			for( int y = 0; y < height; y++ ) {
				float kd = disortion.getValue( 
						1f/height*x, 
						(1f / framesPerPerlin * (frame*.1f) + ( 1f / height * y ) ) );
				
				float k = perlin.getValue( 
						1f/width*x*3f  +  ((kd*.5f)-.5f), 
						(1f / framesPerPerlin * (frame*.5f)) + ( 1f / height * y ) );
				float mk = fireDispose.getValue( 1f / height * y );
				
				int fc = ColorGradient.cubic( k+.2f,0xff_ff0000, 0xff_ffff00 );
				if( mk < k )
					fc = 0xff_000000;
				
				//int fc = ColorGradient.cubic( kd, 0xff000000, 0xffffffff );
				r.setPixel( fc, x, y );
			}
	
		System.out.println( "glow (" + frame + ")" );
		Convolution.lin( r, r, Convolution.cubicFilter( 5 ), 5 );
		RasterManager o = new RasterManager( width, height );
		Convolution.lin( r, o, Convolution.cubicFilter( 100 ), 100 );
		
		System.out.println( "combine (" + frame + ")" );
		Combine.max( o, r, r );
		
		return IOLoader.create( r );
	}
	
	private static class FireDispose implements IFunction {

		@Override
		public float getValue( float x ) {
			return .4f * x + .4f;
		}
		
	}
}
